﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;

namespace KDSugar.Galaxy.API.SaveOrDraft
{
    /// <summary>
    /// 单据保存操作指令
    /// </summary>
    public class SaveCommand : Base.BaseCommand
    {
        /// <summary>
        /// 单据保存操作指令URL
        /// </summary>
        public const string SAVE_COMMAND_URL = "/Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Save.common.kdsvc";

        /// <summary>
        /// 单据保存操作指令初始化
        /// </summary>
        /// <param name="_client"></param>
        public SaveCommand(GalaxyCloudAPIClient _client)
            : base(SAVE_COMMAND_URL, null, _client)
        {

        }

        /// <summary>
        /// （仅用作暂存指令相关）
        /// </summary>
        /// <param name="_url"></param>
        /// <param name="_client"></param>
        protected SaveCommand(string _url,GalaxyCloudAPIClient _client)
            : base(_url, null, _client)
        {

        }

        /// <summary>
        /// 验证保存操作返回数据是否符合规则
        /// </summary>
        /// <param name="_responseData">返回数据</param>
        /// <returns></returns>
        public override bool ValidateResponseDataRule(string _responseData)
        {
            return true;
        }

        /// <summary>
        /// 构建保存操作请求内容
        /// </summary>
        /// <returns></returns>
        public override string BuildRequestContent()
        {
            return BuildRequestContentByAppendFormId();
        }

        /// <summary>
        /// 创建者内码
        /// </summary>
        public string Creator { get; set; }

        /// <summary>
        /// 需要更新的字段，数组类型，格式：[key1,key2,...] 注（更新单据体字段得加上单据体key）
        /// </summary>
        public List<string> NeedUpDateFields { get; set; }

        /// <summary>
        /// 需返回结果的字段集合，数组类型，格式：[key,entitykey.key,...] 注（返回单据体字段格式：entitykey.key）
        /// </summary>
        public List<string> NeedReturnFields { get; set; }

        /// <summary>
        /// 是否删除已存在的分录，布尔类型，默认true
        /// </summary>
        public bool IsDeleteEntry { get; set; } = true;

        /// <summary>
        /// 表单所在的子系统内码
        /// </summary>
        public string SubSystemId { get; set; }

        /// <summary>
        /// 是否验证所有的基础资料有效性，默认false
        /// </summary>
        public bool IsVerifyBaseDataField { get; set; } = false;

        /// <summary>
        /// 是否批量填充分录，默认true
        /// </summary>
        public bool IsEntryBatchFill { get; set; } = true;

        /// <summary>
        /// 是否验证标志，默认true
        /// </summary>
        public bool ValidateFlag { get; set; } = true;

        /// <summary>
        /// 是否用编码搜索基础资料，默认true
        /// </summary>
        public bool NumberSearch { get; set; } = true;

        /// <summary>
        /// 交互标志集合，分号分隔，格式："flag1;flag2;..." 
        /// </summary>
        public string InterationFlags { get; set; }

        /// <summary>
        /// 是否自动提交与审核，默认false
        /// <para>注意：启用此参数，保存，提交和审核是在一个事务中</para>
        /// </summary>
        public bool IsAutoSubmitAndAudit { get; set; } = false;

        /// <summary>
        /// 表单数据包
        /// </summary>
        public Dictionary<string, object> Model { get;  private set; }

        /// <summary>
        /// 执行单据保存/暂存操作
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        public SaveOrDraftReturnInfo.SaveOrDraftResultInfo ExecuteSaveBill<T>(T t)
        {
            SaveOrDraftReturnInfo.SaveOrDraftResultInfo result = null;
            Type type = typeof(T);
            if (type != null && t != null)
            {
                #region 获取单据模型业务对象标识
                string _formId = null;
                var saveTableTagObj = type.GetCustomAttributes(typeof(SaveTableTag), false);
                SaveTableTag saveTableTag = (saveTableTagObj != null && saveTableTagObj.Count() > 0) ? 
                    (SaveTableTag)saveTableTagObj[0] : null;
                if (saveTableTag != null)
                    _formId = saveTableTag.TableTagName;
                #endregion
                if (!string.IsNullOrWhiteSpace(_formId))
                {
                    SetFormId(_formId);
                    Dictionary<string, object> _model = new Dictionary<string, object>();
                    #region 遍历单据模型字段标识
                    foreach(var pInfo in type.GetProperties())
                    {
                        if (pInfo != null)
                        {
                            string _field = null;
                            var saveFieldTagObj = pInfo.GetCustomAttributes(typeof(SaveFieldTag), false);
                            SaveFieldTag saveFieldTag = (saveFieldTagObj != null && saveFieldTagObj.Count() > 0) ?
                                (SaveFieldTag)saveFieldTagObj[0] : null;
                            if (saveFieldTag != null)
                                _field = saveFieldTag.FieldTagName;
                            if (!string.IsNullOrWhiteSpace(_field))
                            {
                                var _modelKV = GetModelKV(_field, pInfo.GetValue(t, null));
                                if (_modelKV != null)
                                {
                                    foreach(var _kv in _modelKV)
                                    {
                                        _model.Add(_kv.Key, _kv.Value);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    #endregion
                    Model = _model;
                    var resultData = APIClient.ExecuteCommand(this);
                    if (resultData != null && !string.IsNullOrWhiteSpace(resultData.ResponseData))
                    {
                        string sjexMsg = "未知错误";
                        try
                        {
                            sjexMsg = "返回数据JSON反序列化为对象出错";
                            SaveOrDraftReturnInfo returnInfo = JsonConvert.DeserializeObject<SaveOrDraftReturnInfo>(resultData.ResponseData);
                            if (returnInfo != null)
                            {
                                if (returnInfo.Result != null)
                                {
                                    result = returnInfo.Result;
                                }
                                else
                                {
                                    sjexMsg = "保存/暂存返回信息(Result)为NULL";
                                    throw new Exception(sjexMsg);
                                }
                            }
                            else
                            {
                                sjexMsg = "反序列化后对象为NULL";
                                throw new Exception(sjexMsg);
                            }
                        }
                        catch(Except.ExecuteException ex)
                        {
                            ex.OperateCommandName = GetOperateCommandName();
                            ex.AppendMessage = sjexMsg;
                            ex.ExecuteData = resultData;
                            throw ex;
                        }
                    }
                    else
                    {
                        throw new Exception(Constant.GetExecuteReturnNullErrorStr("保存"));
                    }
                }
                else
                {
                    //未获取到业务对象表示
                    throw new Exception("模型FormId未赋值");
                }
            }
            else
            {
                //传入对象为NULL
                if (type == null)
                {
                    throw new Exception("未获取到数据模型");
                }
                else if (t == null)
                {
                    throw new Exception("传入参数为NULL");
                }
                else
                {
                    throw new Exception("未知错误");
                }
            }
            SetFormId(null);
            return result;
        }

        //private class SaveJsonDesException : Exception
        //{
        //    public string AppendMessage { get; set; }
        //}

        private Dictionary<string,object> GetModelKV(string _key,object _val)
        {
            Dictionary<string, object> result = null;
            if (!string.IsNullOrWhiteSpace(_key))
            {
                result = new Dictionary<string, object>();
                if (_key.IndexOf('.') > 0)
                {
                    string tmpSubKey = _key.Substring(_key.IndexOf('.'), _key.Length - _key.IndexOf('.'));
                    result.Add(_key.Split('.')[0], GetModelKV(tmpSubKey, _val));
                }
                else
                {
                    result.Add(_key, _val);
                }
            }
            return result;
        }
    }
}
